import 'dart:convert';
import 'dart:io';
import 'dart:math' as math;

import 'package:crypto/crypto.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class Util {
  static bool isChinaPhoneLegal(String str) {
    return RegExp(r'^1[3-9]\d{9}$').hasMatch(str);
  }

  static bool isBankCardNumber(String input) {
    return RegExp(r'((^\d{15}$)|(^\d{16}$)|(^\d{19}$))').hasMatch(input);
  }

  static bool isNumber(String input) {
    return RegExp(r'^\d*$').hasMatch(input);
  }

  static bool isMoney(String input) {
    return RegExp(r'((^[1-9]\d*)|^0)(\.\d{0,2}){0,1}$').hasMatch(input);
  }

  static bool isValidDate(String input) {
    return RegExp(r'^\d{4}$').hasMatch(input);
  }

  static String urlStringEncode(String value) {
    if (value == '') {
      return '';
    }
    return jsonEncode(const Utf8Encoder().convert(value));
  }

  static String urlStringDecode(String value) {
    if (value == '') {
      return '';
    }
    var list = <int>[];
    jsonDecode(value).forEach(list.add);
    return const Utf8Decoder().convert(list);
  }

  static String urlMapEncode(Map<String, dynamic> map) {
    return jsonEncode(const Utf8Encoder().convert(json.encode(map)));
  }

  static Map<String, dynamic> urlMapDecode(String value) {
    var list = <int>[];
    jsonDecode(value).forEach(list.add);
    return json.decode(const Utf8Decoder().convert(list));
  }

  static bool isCardId(String cardId) {
    if (cardId.length != 18) {
      return false; // 位数不够
    }
    // 身份证号码正则
    RegExp postalCode = RegExp(r'^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|[Xx])$');
    // 通过验证，说明格式正确，但仍需计算准确性
    if (!postalCode.hasMatch(cardId)) {
      return false;
    }
    //将前17位加权因子保存在数组里
    final List idCardList = ['7', '9', '10', '5', '8', '4', '2', '1', '6', '3', '7', '9', '10', '5', '8', '4', '2'];
    //这是除以11后，可能产生的11位余数、验证码，也保存成数组
    final List idCardYArray = ['1', '0', '10', '9', '8', '7', '6', '5', '4', '3', '2'];
    // 前17位各自乖以加权因子后的总和
    int idCardWiSum = 0;

    for (int i = 0; i < 17; i++) {
      int subStrIndex = int.parse(cardId.substring(i, i + 1));
      int idCardWiIndex = int.parse(idCardList[i]);
      idCardWiSum += subStrIndex * idCardWiIndex;
    }
    // 计算出校验码所在数组的位置
    int idCardMod = idCardWiSum % 11;
    // 得到最后一位号码
    String idCardLast = cardId.substring(17, 18);
    //如果等于2，则说明校验码是10，身份证号码最后一位应该是X
    if (idCardMod == 2) {
      if (idCardLast != 'x' && idCardLast != 'X') {
        return false;
      }
    } else {
      //用计算出的验证码与最后一位身份证号码匹配，如果一致，说明通过，否则是无效的身份证号码
      if (idCardLast != idCardYArray[idCardMod]) {
        return false;
      }
    }
    return true;
  }

  static String formatDate(DateTime date) {
    String answer = date.year.toString();
    if (date.month < 10) {
      answer = '${answer}0${date.month}';
    } else {
      answer = '$answer${date.month}';
    }
    if (date.day < 10) {
      answer = '${answer}0${date.day}';
    } else {
      answer = '$answer${date.day}';
    }
    return answer;
  }

  static String formatTime(DateTime date) {
    String answer = '';
    if (date.hour < 10) {
      answer = '${answer}0${date.hour}';
    } else {
      answer = '$answer${date.hour}';
    }
    if (date.minute < 10) {
      answer = '${answer}0${date.minute}';
    } else {
      answer = '$answer${date.minute}';
    }
    if (date.second < 10) {
      answer = '${answer}r0${date.second}';
    } else {
      answer = '$answer${date.second}';
    }
    return answer;
  }

  static MD5(String data) {
    return md5.convert(utf8.encode(data)).toString().toUpperCase();
  }

  static exitApp() {
    if (Platform.isAndroid) {
      SystemChannels.platform.invokeMethod('SystemNavigator.pop');
    } else if (Platform.isIOS) {
      exit(0);
    }
  }

  static DateTime? fromMicrosecondsSinceEpoch(var microseconds) {
    if (microseconds is String) {
      try {
        return DateTime.fromMicrosecondsSinceEpoch(int.parse(microseconds));
      } catch (e) {
        return null;
      }
    } else if (microseconds is int) {
      return DateTime.fromMicrosecondsSinceEpoch(microseconds);
    }
    return null;
  }

  static DateTime? fromMillisecondsSinceEpoch(var microseconds) {
    if (microseconds is String) {
      try {
        return DateTime.fromMillisecondsSinceEpoch(int.parse(microseconds));
      } catch (e) {
        return null;
      }
    } else if (microseconds is int) {
      return DateTime.fromMillisecondsSinceEpoch(microseconds);
    }
    return null;
  }

  /// 可以创建一个外接圆半径为[R],内接圆半径半径为[r]的[num]角星路径
  static Path nStarPath(int num, double R, double r) {
    Path path = Path();
    double perDegree = 360 / num;
    double degreeA = perDegree / 2 / 2;
    double degreeB = (360 / (num - 1) - degreeA) / 2 + degreeA;

    path.moveTo(math.cos(degree2Radian(degreeA)) * R, (-math.sin(degree2Radian(degreeA)) * R));
    for (int i = 0; i < num; i++) {
      path.lineTo(math.cos(degree2Radian(degreeA + perDegree * i)) * R, -math.sin(degree2Radian(degreeA + perDegree * i)) * R);
      path.lineTo(math.cos(degree2Radian(degreeB + perDegree * i)) * r, -math.sin(degree2Radian(degreeB + perDegree * i)) * r);
    }
    path.close();
    return path;
  }

  /// 角度转弧度公式
  static double degree2Radian(num degree) {
    return (math.pi * degree / 180);
  }

  /// 弧度转角度公式
  static double radian2Degree(num radian) => radian * (180.0 / math.pi);
}
